package app.panchip.bleadvertiseexample;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.example.nirjon.bledemo4_advertising.util.BLEUtil;
import com.lyn.bleadvertiseexampledemo.R;
import static android.bluetooth.le.AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY;
import static android.bluetooth.le.AdvertiseSettings.ADVERTISE_TX_POWER_HIGH;

public class MainActivity extends Activity implements View.OnClickListener {

    private static final int ENABLE_BLUETOOTH = 1234;
    private static final int BLE_PAYLOAD_LENGTH = 11;

    private Button operateBtn;
    private TextView text;
    private EditText addressInput, payloadInput;

    private BluetoothManager myManager;
    private BluetoothAdapter myAdapter;
    private BluetoothLeAdvertiser myAdvertiser;
    private AdvertiseSettings myAdvertiseSettings;
    private AdvertiseData myAdvertiseData;
    AdvertiseCallback myAdvertiseCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            super.onStartSuccess(settingsInEffect);
            Log.v("TAG", "Advertise start succeeds: " + settingsInEffect.toString());
        }

        @Override
        public void onStartFailure(int errorCode) {
            super.onStartFailure(errorCode);
            Log.v("Tag", "Advertise start failed: " + errorCode);
        }
    };

    private boolean advertising;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();
    }

    public void init() {
        text = findViewById(R.id.info);
        addressInput = findViewById(R.id.input_address);
        payloadInput = findViewById(R.id.input_payload);
        operateBtn = findViewById(R.id.operate);
        operateBtn.setOnClickListener(this);

        checkBluetoothState();
    }

    private void checkBluetoothState() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (!bluetoothAdapter.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, ENABLE_BLUETOOTH);
        } else {
            BT_Adv_init();
        }
    }

    private void BT_Adv_init() {
        myManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
        myAdapter = myManager.getAdapter();
        myAdvertiser = myAdapter.getBluetoothLeAdvertiser();

        if (!myAdapter.isMultipleAdvertisementSupported()) {
            findViewById(R.id.operate).setEnabled(false);
            text.setText("Device does not support BLE advertisement.");
            return;
        }

        myAdvertiseSettings = new AdvertiseSettings.Builder()
                .setAdvertiseMode(ADVERTISE_MODE_LOW_LATENCY)
                .setConnectable(true)
                .setTimeout(0)
                .setTxPowerLevel(ADVERTISE_TX_POWER_HIGH)
                .build();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.operate:
                if (advertising) {
                    myAdvertiser.stopAdvertising(myAdvertiseCallback);
                    advertising = false;
                    operateBtn.setText("发送");
                } else {
                    String rawAddress = addressInput.getText().toString();
                    rawAddress = rawAddress.replace(" ", "");
                    rawAddress = rawAddress.toLowerCase();
                    if (rawAddress.length() < 6 || rawAddress.length() > 10) {
                        Toast.makeText(MainActivity.this, "Please input address with length between 3 and 5 bytes", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    byte[] address = new byte[rawAddress.length()/2];
                    for (int i = 0; i < address.length; ++i) {
                        address[i] = strToByte(rawAddress.substring(i*2, (i+1)*2));
                    }

                    String rawPayload = payloadInput.getText().toString();
                    rawPayload = rawPayload.replace(" ", "");
                    rawPayload = rawPayload.toLowerCase();
                    if (rawPayload.length() < 2) {
                        Toast.makeText(MainActivity.this, "The payload is at least 1 byte", Toast.LENGTH_SHORT).show();
                        return;
                    }
                    byte[] payload = new byte[rawPayload.length()/2];
                    for (int i = 0; i < payload.length; ++i) {
                        payload[i] = strToByte(rawPayload.substring(i*2, (i+1)*2));
                    }

                    final byte[] calculatedPayload = new byte[address.length+payload.length+5];
                    BLEUtil.get_rf_payload(address, address.length, payload, payload.length, calculatedPayload);

                    myAdvertiseData = new AdvertiseData.Builder()
                            .addManufacturerData(65520, calculatedPayload)
                            .build();

                    myAdvertiser.startAdvertising(myAdvertiseSettings, myAdvertiseData, myAdvertiseCallback);
                    text.setText(bytesToStr(calculatedPayload,address.length+payload.length+5));
                    advertising = true;
                    operateBtn.setText("停止");
                }
                break;
        }
    }

    @Override
    protected void onActivityResult(int RequestCode, int resultCode, Intent data) {
        if (RequestCode == ENABLE_BLUETOOTH) {
            switch (resultCode) {
                case RESULT_OK:
                    Toast.makeText(MainActivity.this, "蓝牙已开启", Toast.LENGTH_SHORT).show();
                    BT_Adv_init();
                    break;
                default:
                    Toast.makeText(MainActivity.this, "需开启蓝牙", Toast.LENGTH_SHORT).show();
                    MainActivity.this.finish();
            }
        }
    }

    /* -------------------------------------------------------------------------------------- */

    private static final String HEX = "0123456789abcdef";

    private byte strToByte(String str) {
        byte res = 0;
        if (str.length() == 1) {
            res = (byte)(HEX.indexOf(str) & 0xff);
        } else {
            res = (byte) ((charToByte(str.charAt(0)) << 4) | charToByte(str.charAt(1)));
        }
        return res;
    }

    private byte charToByte(char c) {
        return (byte) HEX.indexOf(c);
    }

    private String bytesToStr(byte[] bytes, int len) {
        StringBuilder builder = new StringBuilder("");
        for (int i = 0; i != len; ++i) {
            if ((int)(bytes[i] & 0xf0) == 0) {
                builder.append("0");
                builder.append(HEX.charAt(bytes[i]&0x0f));
            } else {
                builder.append(HEX.charAt((bytes[i]>>4)&0x0f));
                builder.append(HEX.charAt(bytes[i]&0x0f));
            }
            builder.append(" ");
        }
        return builder.toString();
    }

    static String byteArrToString(byte[] data){

        char[] result = new char[data.length];
        for(int i = 0; i < data.length; i++){
            result[i] = (char) data[i];
        }
        return new String(result);
    }
}
